home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / drdobbs / 1992 / 06 / dflt12 / huffc.c < prev    next >
Text File  |  1992-03-26  |  3KB  |  115 lines

  1. /* ------------------- huffc.c -------------------- */
  2.  
  3. #include "dflat.h"
  4. #include "htree.h"
  5.  
  6. extern struct htree *ht;
  7. extern int root;
  8. extern int treect;
  9.  
  10. static void compress(FILE *, int, int);
  11. static void outbit(FILE *fo, int bit);
  12.  
  13. int fgetcx(FILE *fi)
  14. {
  15.     int c;
  16.  
  17.     /* ------- bypass comments ------- */
  18.     if ((c = fgetc(fi)) == '#')
  19.         while (c != '\n' && c != EOF)
  20.             c = fgetc(fi);
  21.     return c;
  22. }
  23.  
  24. void main(int argc, char *argv[])
  25. {
  26.     FILE *fi, *fo;
  27.     int c;
  28.     BYTECOUNTER bytectr = 0;
  29.  
  30.     if (argc < 3)   {
  31.         printf("\nusage: huffc infile outfile");
  32.         exit(1);
  33.     }
  34.  
  35.     if ((fi = fopen(argv[1], "rb")) == NULL)    {
  36.         printf("\nCannot open %s", argv[1]);
  37.         exit(1);
  38.     }
  39.     if ((fo = fopen(argv[2], "wb")) == NULL)    {
  40.         printf("\nCannot open %s", argv[2]);
  41.         fclose(fi);
  42.         exit(1);
  43.     }
  44.  
  45.     ht = calloc(256, sizeof(struct htree));
  46.  
  47.     /* - read the input file and count character frequency - */
  48.     while ((c = fgetcx(fi)) != EOF)   {
  49.         c &= 255;
  50.         ht[c].cnt++;
  51.         bytectr++;
  52.     }
  53.  
  54.     /* ---- build the huffman tree ---- */
  55.     buildtree();
  56.  
  57.     /* --- write the byte count to the output file --- */
  58.     fwrite(&bytectr, sizeof bytectr, 1, fo);
  59.  
  60.     /* --- write the tree count to the output file --- */
  61.     fwrite(&treect, sizeof treect, 1, fo);
  62.  
  63.     /* --- write the root offset to the output file --- */
  64.     fwrite(&root, sizeof root, 1, fo);
  65.  
  66.     /* -- write the tree to the output file -- */
  67.     for (c = 256; c < treect; c++)   {
  68.         int lf = ht[c].left;
  69.         int rt = ht[c].right;
  70.         fwrite(&lf, sizeof lf, 1, fo);
  71.         fwrite(&rt, sizeof rt, 1, fo);
  72.     }
  73.  
  74.     /* ------ compress the file ------ */
  75.     fseek(fi, 0L, 0);
  76.     while ((c = fgetcx(fi)) != EOF)
  77.         compress(fo, (c & 255), 0);
  78.     outbit(fo, -1);
  79.     fclose(fi);
  80.     fclose(fo);
  81.     free(ht);
  82.     exit(0);
  83. }
  84.  
  85. /* ---- compress a character value into a bit stream ---- */
  86. static void compress(FILE *fo, int h, int child)
  87. {
  88.     if (ht[h].parent != -1)
  89.         compress(fo, ht[h].parent, h);
  90.     if (child)  {
  91.         if (child == ht[h].right)
  92.             outbit(fo, 0);
  93.         else if (child == ht[h].left)
  94.             outbit(fo, 1);
  95.     }
  96. }
  97.  
  98. static char out8;
  99. static int ct8;
  100.  
  101. /* -- collect and write bits to the compressed output file -- */
  102. static void outbit(FILE *fo, int bit)
  103. {
  104.     if (ct8 == 8 || bit == -1)  {
  105.         while (ct8 < 8)    {
  106.             out8 <<= 1;
  107.             ct8++;
  108.         }
  109.         fputc(out8, fo);
  110.         ct8 = 0;
  111.     }
  112.     out8 = (out8 << 1) | bit;
  113.     ct8++;
  114. }
  115.